package chapter12Lock.solution;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 带有Condition控制的仓库类
 * Created by LinGer on 2019/6/19
 */
public class DepotWithCondition {

    /**
     * 独占锁
     */
    private Lock lock;

    /**
     * 仓库容量
     */
    private int capacity;

    /**
     * 仓库的现有产品数量
     */
    private int size;

    /**
     * 生产条件
     */
    private Condition fullCondition;

    /**
     * 消费条件
     */
    private Condition emptyCondition;

    public DepotWithCondition(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        //默认创建非公平锁
        this.lock = new ReentrantLock();
        this.fullCondition = lock.newCondition();
        this.emptyCondition = lock.newCondition();
    }

    public void produce(int val) {
        //获取锁
        lock.lock();
        try {
            int left = val;
            while (left > 0) {
                if (size >= capacity) {
                    fullCondition.await();
                }

                int increment = (size + left) > capacity ? (capacity - size) : left;
                size += increment;
                left -= increment;
                System.out.println(Thread.currentThread().getName() + " produce: " + val + " --> left=" + left + " ,increment=" + increment + " ,size=" + size);
                //通知消费者可以消费了
                emptyCondition.signal();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //释放锁
            lock.unlock();
        }
    }

    public void consume(int val) {
        lock.lock();
        try {
            int left = val;
            while (left > 0) {
                if (size <= 0) {
                    emptyCondition.await();
                }

                int decrease = (size < left) ? size : left;
                size -= decrease;
                left -= decrease;

                System.out.println(Thread.currentThread().getName() + " consume: " + val + " <-- left=" + left + " ,decrease=" + decrease + " ,size=" + size);
                //通知生产者生产
                fullCondition.signal();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}
